package org.zachary.imitation.raft;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zachary.imitation.raft.option.NodeOptions;
import org.zachary.imitation.raft.util.NodeBuilder;
import org.zachary.utils.lang.StringUtils;

/**
 * 集群服务的类，该类是启动集群的入口
 *
 * Created by guozhaokun on 2024/8/30 21:34.
 */
public class RaftGroupService {
	private Logger logger = LoggerFactory.getLogger(RaftGroupService.class);

	/** 集群服务是否启动的标志 */
	private volatile boolean started = false;
	/** 当节点的信息 */
	private PeerId serverId;
	/** 节点所需要的配置参数 */
	private NodeOptions nodeOptions;
	/** 节点与节点之间进行通信的 RPC 服务端 */
	private RpcServer rpcServer;
	/** 当前节点所属的 groupId，也就是集群 ID */
	private String groupId;
	/** 当前节点本身 */
	private Node node;

	public RaftGroupService(final String group, final PeerId serverId, final NodeOptions nodeOptions, final RpcServer rpcServer) {
		this(group, serverId, nodeOptions, rpcServer, false);
	}

	public RaftGroupService(final String groupId, final PeerId serverId, final NodeOptions nodeOptions, final RpcServer rpcServer, final boolean sharedRpcServer) {
		this.groupId = groupId;
		this.serverId = serverId;
		this.nodeOptions = nodeOptions;
		this.rpcServer = rpcServer;
//		this.sharedRpcServer = sharedRpcServer;
	}

	/** 启动当前节点以及节点所在集群的方法 */
	public synchronized Node start() {
		return start(true);
	}

	/** 启动当前节点以及节点所在集群的方法 */
	public synchronized Node start(final boolean startRpcServer) {
		if (this.started) {
			return this.node;
		}
		// 对节点 ID 和集群 ID 做非空检验
		if (this.serverId == null || this.serverId.getEndpoint() == null || this.serverId.getEndpoint().equals(new Endpoint(PeerId.IP_ANY, 0))) {
			throw new IllegalArgumentException("Blank serverId:" + this.serverId);
		}
		if (StringUtils.isBlank(this.groupId)) {
			throw new IllegalArgumentException("Blank group:" + this.groupId);
		}

		// 把当前节点的 ip:port 地址信息交给节点管理器来管理
		NodeManager.getInstance().addAddress(this.serverId.getEndpoint());
		// 创建当前服务器代表的节点并执行节点的初始化操作
		this.node = NodeBuilder.createAndInitRaftNode(this.groupId, this.serverId, this.nodeOptions);

		if (startRpcServer) {
			//启动RPC服务端
//			this.rpcServer.init(null);
		} else {
			logger.warn("RPC server is not started in RaftGroupService.");
		}
		this.started = true;
		logger.info("Start the RaftGroupService successfully.");
		return this.node;
	}
}
